using System;
using System.IO;
using Hive.Core.Common.Shell;

namespace Hive.Core.Model.Commands
{
    /// <summary>
    /// Base class for commands that act on a package branch.
    /// </summary>
    public abstract class BasePackageBranchCommand : BaseHiveCommand
    {
        /// <summary>
        /// Gets or sets the package name, or null to locate it automatically.
        /// </summary>
        public string PackageName { get; set; }

        /// <summary>
        /// Gets or sets the branch name, or null to locate it automatically.
        /// </summary>
        public string BranchName { get; set; }

        /// <inheritdoc />
        sealed protected override CommandExitCode ExecuteWithHive(IHiveManager hiveManager, IShell shell, IHive hive)
        {
            string packageName, branchName;
            if (!ResolvePackageBranchDirectory(shell, hive, out packageName, out branchName))
            {
                shell.Echo(MessageSeverity.Error, string.Format("Could not determine the package branch for '{0}'.  Please specify the package branch explicitly.", shell.CurrentDirectory.FullName));
                return CommandExitCode.Failure;
            }

            IPackageBranch packageBranch = hive.GetPackage(packageName).GetBranch(branchName);
            return ExecuteWithPackageBranch(hiveManager, shell, packageBranch);
        }

        /// <summary>
        /// Executes the command with the package branch that was found.
        /// </summary>
        /// <param name="hiveManager">The hive manager, not null.</param>
        /// <param name="shell">The shell, not null.</param>
        /// <param name="packageBranch">The package branch, not null.</param>
        /// <returns>The command exit code.</returns>
        protected abstract CommandExitCode ExecuteWithPackageBranch(IHiveManager hiveManager, IShell shell, IPackageBranch packageBranch);

        private bool ResolvePackageBranchDirectory(IShell shell, IHive hive, out string packageName, out string branchName)
        {
            if (PackageName != null)
            {
                packageName = PackageName;
                branchName = BranchName ?? hive.SourceRepository.DefaultBranchName;
                return true;
            }

            return hive.FindPackageBranch(shell.CurrentDirectory, out packageName, out branchName);
        }
    }
}